<template>
  <div
    class="flex border-t border-b main-wrap border-color w-full"
    :class="scene == 'select' ? 'h-[40vh]' : 'h-full'"
  >
    <!-- 分组 -->
    <div class="group-wrap w-[180px] p-[15px] h-full border-r border-color flex flex-col">
      <el-input
        v-model="categoryParam.name"
        class="m-0"
        :placeholder="t('upload.attachmentCategoryPlaceholder')"
        clearable
        prefix-icon="Search"
        @input="getAttachmentCategoryList()"
      />
      <div class="group-list flex-1 my-[10px] h-0">
        <el-scrollbar>
          <div
            class="group-item p-[10px] leading-none text-xs rounded cursor-pointer"
            :class="{ active: attachmentParam.cate_id == 0 }"
            @click="attachmentParam.cate_id = 0"
          >
            全部
          </div>
          <div
            class="group-item px-[10px] text-xs rounded cursor-pointer flex"
            v-for="(item, index) in attachmentCategory.data"
            :key="index"
            :class="{ active: attachmentParam.cate_id == item.typeId }"
          >
            <div
              class="flex-1 leading-none truncate py-[10px]"
              @click="attachmentParam.cate_id = item.typeId"
              >{{ item.typeName }}</div
            >
            <div
              class="leading-none operate py-[10px]"
              v-if="scene == 'attachment' && prop.type != 'icon'"
            >
              <!-- 图片操作 -->
              <el-dropdown :hide-on-click="false" v-if="scene == 'attachment'">
                <icon name="element MoreFilled" class="cursor-pointer ml-[10px]" size="14px" />
                <template #dropdown>
                  <el-dropdown-menu>
                    <el-dropdown-item class="text-center">
                      <popover-input
                        :placeholder="t('upload.attachmentCategoryPlaceholder')"
                        @confirm="updateAttachmentCategory($event, index)"
                        v-model="item.typeName"
                      >
                        <span>{{ t('edit') }}</span>
                      </popover-input>
                    </el-dropdown-item>
                    <el-dropdown-item @click="deleteAttachmentCategory(index)">
                      <div class="text-center w-full">{{ t('delete') }}</div>
                    </el-dropdown-item>
                  </el-dropdown-menu>
                </template>
              </el-dropdown>
            </div>
          </div>
        </el-scrollbar>
      </div>
      <!-- 添加分组 -->
      <popover-input
        :placeholder="t('upload.attachmentCategoryPlaceholder')"
        @confirm="addAttachmentCategory"
        v-model="attachmentCategoryName"
        v-if="prop.type != 'icon'"
      >
        <el-button class="w-100%!">{{ t('upload.addAttachmentCategory') }}</el-button>
      </popover-input>
    </div>

    <!-- 素材 -->
    <div class="attachment-list-wrap flex flex-col p-[15px] flex-1 overflow-hidden">
      <el-row :gutter="15" class="h-[32px]">
        <el-col :span="10">
          <div class="flex">
            <el-upload
              :action="uploadUrl"
              :auto-upload="true"
              :data="data"
              :disabled="formLoading"
              :multiple="true"
              :on-change="handleFileChange"
              :on-error="submitFormError"
              :on-exceed="handleExceed"
              :on-success="submitFormSuccess"
              :http-request="httpRequest"
              ref="uploadRef"
              v-if="prop.type != 'icon'"
            >
              <el-button type="primary">{{ t('upload.upload' + type) }} {{ isOpen }}</el-button>
            </el-upload>
            <div v-if="scene == 'attachment' && prop.type != 'icon'">
              <el-button
                v-if="operate === false"
                class="ml-[10px]"
                type="primary"
                @click="operate = true"
                >{{ t('edit') }}</el-button
              >
              <el-button v-else class="ml-[10px]" type="primary" @click="operate = false">{{
                t('complete')
              }}</el-button>
            </div>
          </div>
        </el-col>
        <el-col :span="14" class="text-right">
          <el-input
            v-model="attachmentParam.name"
            class="m-0 !w-[200px]"
            clearable
            :placeholder="t('upload.placeholder' + type + 'Name')"
            prefix-icon="Search"
            @input="getAttachmentList()"
          />
        </el-col>
      </el-row>
      <div class="flex-1 my-[15px] h-0" v-loading="attachment.loading">
        <el-scrollbar>
          <!-- 选择弹出框 -->
          <div
            class="flex flex-wrap"
            v-if="attachment.data.length && (operate === true || scene != 'attachment')"
          >
            <div
              class="attachment-item mr-[10px]"
              :class="scene == 'select' ? 'w-[100px]' : 'w-[120px]'"
              v-for="(item, index) in attachment.data"
              :key="index"
            >
              <div
                class="attachment-wrap w-full rounded cursor-pointer overflow-hidden relative flex items-center justify-center"
                :class="scene == 'select' ? 'h-[100px]' : 'h-[120px]'"
                @click="selectFile(item)"
              >
                <el-image :src="img(item.url)" fit="contain" v-if="type == '1'" />
                <video :src="img(item.url)" v-else-if="type == '2'" />
                <icon :name="item.url" size="24px" v-else-if="type == 'icon'" />
                <icon name="element Document " size="24px" v-else></icon>

                <div
                  class="absolute z-[1] flex items-center justify-center w-full h-full inset-0 bg-black bg-opacity-60"
                  v-show="selectedFile[item.id]"
                >
                  <icon name="element Select" color="#fff" size="40px" />
                  <div class="file-box-active absolute z-[1] bottom-0 right-0 w-full h-full">
                    <span class="absolute bottom-[2px] right-[2px] text-white z-[2] leading-none">{{
                      getFileIndex(item.id)
                    }}</span>
                  </div>
                </div>
              </div>

              <div class="flex items-center">
                <el-tooltip placement="top">
                  <template #content>{{ item.name }}</template>
                  <div class="truncate my-[10px] cursor-pointer text-base flex-1 text-center">{{
                    item.name
                  }}</div>
                </el-tooltip>
                <!-- 图片操作 -->
                <el-dropdown
                  :hide-on-click="false"
                  v-if="scene == 'attachment'"
                  class="attachment-action hidden"
                >
                  <icon name="element MoreFilled" class="cursor-pointer ml-[8px]" size="14px" />
                  <template #dropdown>
                    <el-dropdown-menu>
                      <el-dropdown-item
                        class="text-center"
                        @click="previewImage(index)"
                        v-if="item.type.includes('image')"
                      >
                        <div class="text-center w-full">{{ t('lookOver') }}</div>
                      </el-dropdown-item>
                      <el-dropdown-item
                        class="text-center"
                        @click="previewVideo(index)"
                        v-if="item.type.includes('video')"
                      >
                        <div class="text-center w-full">{{ t('lookOver') }}</div>
                      </el-dropdown-item>
                      <el-dropdown-item class="text-center" @click="moveAttachmentEvent(index)">
                        <div class="text-center w-full">{{ t('upload.move') }}</div>
                      </el-dropdown-item>
                      <el-dropdown-item @click="deleteAttachmentEvent(index)">
                        <div class="text-center w-full">{{ t('delete') }}</div>
                      </el-dropdown-item>
                    </el-dropdown-menu>
                  </template>
                </el-dropdown>
              </div>
            </div>
          </div>

          <!-- 素材管理 -->
          <div class="flex flex-wrap" v-else-if="attachment.data.length && operate === false">
            <div
              class="attachment-item mr-[10px] w-[120px]"
              v-for="(item, index) in attachment.data"
              :key="index"
            >
              <div
                class="attachment-wrap w-full rounded cursor-pointer overflow-hidden relative flex items-center justify-center h-[120px]"
              >
                <el-image
                  :src="img(item.url)"
                  fit="contain"
                  v-if="type == '1'"
                  :preview-src-list="item.image_list"
                />
                <template v-else-if="type == '2'">
                  <video
                    :src="img(item.url)"
                    v-if="item.type.includes('video')"
                    @click="previewVideo(index)"
                  ></video>
                  <WxVoicePlayer
                    class="h-130px! w-100%! text-center flex items-center justify-center m-b-4px"
                    v-else-if="item.type.includes('audio')"
                    :url="item.url"
                  />
                </template>

                <icon :name="item.url" size="24px" v-else-if="type == 'icon'"></icon>
                <el-link type="primary" v-else :href="item.url" :underline="false" target="_blank">
                  <icon name="element Document " size="24px"></icon
                ></el-link>
              </div>
              <div class="flex items-center">
                <el-tooltip placement="top">
                  <template #content>{{ item.name }}</template>
                  <div class="truncate my-[10px] cursor-pointer text-base flex-1 text-center">{{
                    item.name
                  }}</div>
                </el-tooltip>
              </div>
            </div>
          </div>
          <div
            class="flex absolute top-0 left-0 right-0 bottom-0 items-center justify-center"
            v-else
          >
            <div class="flex flex-col items-center" v-if="!attachment.loading">
              <img
                src="@/views/app/assets/images/no_attachment.png"
                class="max-w-[130px] max-h-[130px] mb-[15px]"
              />
              <span class="text-[var(--el-text-color-secondary)] text-[14px]">{{
                type == 'icon' ? t('upload.iconEmpty') : t('upload.attachmentEmpty')
              }}</span>
            </div>
          </div>
        </el-scrollbar>
      </div>
      <el-row :gutter="20">
        <el-col :span="8" v-if="scene == 'attachment' && operate === true">
          <div class="flex items-center">
            <el-checkbox v-model="selectAll" :label="t('selectAll')" size="large" />
            <!-- <el-button
              class="ml-[15px]"
              :disabled="batchOperateDisabled"
              @click="deleteAttachmentEvent()"
              >{{ t('delete') }}</el-button
            > -->
            <el-button :disabled="batchOperateDisabled" @click="moveAttachmentEvent()">{{
              t('upload.move')
            }}</el-button>
          </div>
        </el-col>
        <el-col :span="24">
          <div class="flex h-full justify-end items-center">
            <el-pagination
              v-model:current-page="attachment.page"
              :small="true"
              v-model:page-size="attachment.limit"
              :page-sizes="[10, 20, 30, 40, 60]"
              layout="total, sizes, prev, pager, next, jumper"
              :total="attachment.total"
              @size-change="getAttachmentList()"
              @current-change="getAttachmentList"
            />
          </div>
        </el-col>
      </el-row>
    </div>

    <template v-if="scene == 'attachment'">
      <!-- 移动附件分组 -->
      <el-dialog
        v-model="moveAttachmentData.visible"
        :title="t('upload.moveCategory')"
        width="350px"
      >
        <el-form label-width="60px">
          <el-form-item :label="t('upload.moveTo')" style="margin-bottom: 0">
            <el-select v-model="moveAttachmentData.cateId" class="input-width">
              <el-option
                :label="item.typeName"
                :value="item.typeId"
                v-for="(item, index) in attachmentCategory.data"
                :key="index"
              />
            </el-select>
          </el-form-item>
        </el-form>

        <template #footer>
          <span class="dialog-footer">
            <el-button @click="moveAttachmentData.visible = false">{{ t('cancel') }}</el-button>
            <el-button
              type="primary"
              :loading="moveAttachmentData.loading"
              @click="moveAttachmentData.confirm()"
              >{{ t('confirm') }}</el-button
            >
          </span>
        </template>
      </el-dialog>

      <!-- 图片预览 -->
      <el-image-viewer
        :url-list="previewImageList"
        v-if="imageViewer.show"
        @close="imageViewer.show = false"
        :initial-index="imageViewer.index"
        :zoom-rate="1"
      />

      <!-- 视频预览 -->
      <el-dialog
        v-model="videoViewer.visible"
        width="50%"
        align-center
        :destroy-on-close="true"
        custom-class="video-preview"
      >
        <video-player :src="videoViewer.src" width="100%" />
      </el-dialog>
    </template>
  </div>
</template>

<script lang="ts" setup>
import { ref, reactive, watch, computed, toRaw } from 'vue'
import { t } from '@/lang'
const message = useMessage() // 消息弹窗

import * as FileApi from '@/api/infra/file'
import videoPlayer from '@/components/video-player/index.vue'
import WxVoicePlayer from '@/views/mp/components/wx-voice-play'

import { debounce, img } from '@/utils/common'
import { ElMessage, ElMessageBox } from 'element-plus'
import icon from '@/views/app/components/icon/index.vue'
import { handleTree } from '@/utils/tree'
import { useUpload } from '@/components/UploadFile/src/useUpload'
// 上传文件
const { uploadUrl, httpRequest } = useUpload()
const formLoading = ref(false) // 表单的加载中

const attachmentCategoryName = ref('')
const operate = ref(false)
const prop = defineProps({
  // 选择数量限制
  limit: {
    type: Number,
    default: 1
  },
  type: {
    type: String,
    default: 'image'
  },
  // 场景
  scene: {
    type: String,
    default: 'select' // select 选择图片 attachment 素材中心
  }
})

/** 处理上传的文件发生变化 */
const data = ref({ path: '', typeId: undefined })

const handleFileChange = (file) => {
  data.value.path = file.name
}

/** 文件数超出提示 */
const handleExceed = (): void => {
  message.error('最多只能上传一个文件！')
}

/** 文件上传成功处理 */
const emit = defineEmits(['success']) // 定义 success 事件，用于操作成功后的回调
const submitFormSuccess = () => {
  // 清理
  formLoading.value = false
  // 提示成功，并刷新
  message.success(t('common.createSuccess'))
  unref(uploadRef)?.clearFiles()
  getAttachmentList()
}

/** 上传错误提示 */
const submitFormError = (): void => {
  message.error('上传失败，请您重新上传！')
  formLoading.value = false
}

// 选中的文件
const selectedFile: Record<string, any> = reactive({})

const selectedFileIndex: any = reactive([])

const attachmentCategory: Record<string, any> = reactive({
  data: []
})

const attachment: Record<string, any> = reactive({
  loading: true,
  page: 1,
  total: 0,
  limit: prop.scene == 'select' ? 10 : 20,
  data: []
})

if (prop.scene == 'select') {
  attachment.limit = 10
  if (prop.type == 'icon') {
    attachment.limit = 20
  }
} else {
  attachment.limit = 20
  if (prop.type == 'icon') {
    attachment.limit = 30
  }
}

const categoryParam = reactive({
  name: ''
})

const attachmentParam = reactive({
  name: '',
  cate_id: 0
})

/**
 * 查询分组
 */
const getAttachmentCategoryList = debounce(async () => {
  const res = await FileApi.getSimpleDirList()
  let dirList = [] as Tree[]
  dirList.push(...handleTree(res, 'typeId'))
  attachmentCategory.data = dirList
  // const getFn = prop.type == 'icon' ? getIconCategoryList : attachmentCategoryList
  // getFn({
  //   type: prop.type,
  //   ...categoryParam
  // })
  //   .then((res) => {
  //     attachmentCategory.data = res.data
  //   })
  //   .catch(() => {})
})

getAttachmentCategoryList()

/**
 * 查询图片
 */
const getAttachmentList = debounce((page: number = 1) => {
  const getFn = FileApi.getFilePage

  attachment.loading = true
  attachment.page = page
  getFn({
    pageNo: attachment.page,
    pageSize: attachment.limit,
    fileType: prop.type,
    name: attachmentParam.name,
    typeId: attachmentParam.cate_id == 0 ? undefined : attachmentParam.cate_id
  })
    .then((res) => {
      attachment.data = res.list
      attachment.total = res.total
      attachment.loading = false
      prop.scene == 'attachment' && clearSelected()

      if (prop.type != 'icon') {
        for (let i = 0; i < attachment.data.length; i++) {
          attachment.data[i]['image_list'] = []
          attachment.data[i]['image_list'].push(img(res.list[i]['url']))
        }
      }
    })
    .catch(() => {
      attachment.loading = false
    })
})
getAttachmentList()

watch(
  () => attachmentParam.cate_id,
  () => {
    getAttachmentList()
  }
)

/**
 * 添加分组
 */
const addAttachmentCategory = async (name: string) => {
  const data = {
    parentId: 0,
    typeName: name,
    sort: 0,
    status: 0
  } as unknown as FileApi.DirVO

  await FileApi.createDir(data)
  message.success(t('common.createSuccess'))
  attachmentCategoryName.value = ''

  getAttachmentCategoryList(1)
}

/**
 * 编辑分组
 * @param name
 * @param index
 */
const updateAttachmentCategory = async (name: string, index: number) => {
  const data = {
    parentId: 0,
    typeName: name,
    sort: 0,
    status: 0,
    typeId: attachmentCategory.data[index].typeId
  } as unknown as FileApi.DirVO

  await FileApi.updateDir(data)
  message.success(t('common.updateSuccess'))
  attachmentCategoryName.value = ''

  getAttachmentCategoryList(1)
}

/**
 * 删除分组
 */
const deleteAttachmentCategory = (index: number) => {
  ElMessageBox.confirm(t('upload.deleteCategoryTips'), t('warning'), {
    confirmButtonText: t('confirm'),
    cancelButtonText: t('cancel'),
    type: 'warning'
  }).then(async () => {
    await FileApi.deleteDir(attachmentCategory.data[index].typeId)
    message.success(t('common.delSuccess'))
    attachmentCategoryName.value = ''

    getAttachmentCategoryList(1)
  })
}

const uploadRef = ref<Record<string, any> | null>(null)

// 全选
const selectAll = ref(false)
watch(selectAll, () => {
  if (selectAll.value) {
    const keys = Object.keys(toRaw(selectedFile))
    attachment.data.forEach((item: Record<string, any>) => {
      if (!keys.includes(item.id)) selectedFile[item.id] = toRaw(item)
    })
  } else {
    clearSelected()
  }
})

/**
 * 清空选中
 */
const clearSelected = () => {
  const keys = Object.keys(toRaw(selectedFile))
  if (keys.length) {
    keys.forEach((key) => {
      delete selectedFile[key]
    })
    selectAll.value = false
  }
}

/**
 * 选择文件
 */
const selectFile = (data: any) => {
  if (selectedFile[data.id]) {
    delete selectedFile[data.id]
    selectedFileIndex.splice(selectedFileIndex.indexOf(data.id), 1)
  } else if (prop.scene == 'select') {
    const keys = Object.keys(toRaw(selectedFile))
    const length = keys.length
    if (prop.limit == 1 && length == prop.limit) {
      delete selectedFile[keys[0]]
      selectedFileIndex.splice(selectedFileIndex.indexOf(keys[0]), 1)
    } else if (length >= prop.limit) {
      ElMessage.info(t('upload.triggerUpperLimit'))
      return
    }
    selectedFile[data.id] = toRaw(data)
    selectedFileIndex.push(data.id)
  } else {
    selectedFile[data.id] = toRaw(data)
    selectedFileIndex.push(data.id)
  }
}

// 获取当前选中文件的下标
const getFileIndex = (id: any) => {
  let index = selectedFileIndex.indexOf(id)
  if (index == -1) return 0
  return index + 1
}

/**
 * 删除附件
 * @param index
 */
const deleteAttachmentEvent = (index: number | null = null) => {
  const ids = index === null ? Object.keys(toRaw(selectedFile)) : [attachment.data[index].id]

  ElMessageBox.confirm(t('upload.deleteAttachmentTips'), t('warning'), {
    confirmButtonText: t('confirm'),
    cancelButtonText: t('cancel'),
    type: 'warning'
  }).then(async () => {
    await FileApi.deleteFile(ids)
    getAttachmentList()
  })
}

/**
 * 移动附件
 */
const moveAttachmentData: Record<string, any> = reactive({
  cateId: '',
  loading: false,
  visible: false
})

const moveAttachmentEvent = (index: number | null = null) => {
  const ids = index === null ? Object.keys(toRaw(selectedFile)) : [attachment.data[index].id]
  moveAttachmentData.visible = true
  moveAttachmentData.cateId = attachmentCategory.data[0].typeId

  moveAttachmentData.confirm = async () => {
    moveAttachmentData.loading = true
    await FileApi.fileExchange({ typeId: moveAttachmentData.cateId, ids: ids })
    moveAttachmentData.visible = false
    moveAttachmentData.loading = false
    getAttachmentList()
  }
}

// 批量操作是否可操作
const batchOperateDisabled = ref(true)
watch(selectedFile, () => {
  batchOperateDisabled.value = Object.keys(toRaw(selectedFile)).length == 0
})

/**
 * 查看图片
 */
const imageViewer = reactive({
  show: false,
  index: 0
})

const previewImage = (index: number) => {
  imageViewer.show = true
  imageViewer.index = index
}
const previewImageList = computed(() => {
  return toRaw(attachment.data).map((item: Record<string, any>) => {
    return img(item.url)
  })
})

/**
 * 视频预览
 */
const videoViewer = reactive({
  visible: false,
  src: ''
})

const previewVideo = (index: number) => {
  videoViewer.visible = true
  videoViewer.src = img(attachment.data[index].url)
}

defineExpose({
  selectedFile,
  selectedFileIndex
})
</script>

<style lang="scss" scoped>
.group-list {
  .group-item {
    height: 32px;
    margin-top: 3px;

    .operate {
      display: none;
    }

    &.active {
      background-color: var(--el-color-primary-light-9);
      color: var(--el-color-primary);
    }

    &:hover {
      background-color: var(--el-color-primary-light-9);

      .operate {
        display: block;
      }
    }
  }
}

.attachment-item:hover {
  .attachment-action {
    display: block;
  }
}

.attachment-list-wrap {
  .attachment-wrap {
    background: var(--el-border-color-extra-light);
  }
}
.file-box-active {
  &:after {
    content: '';
    display: block;
    position: absolute;
    border: 15px solid;
    border-bottom-color: var(--el-color-primary);
    border-right-color: var(--el-color-primary);
    border-top-color: transparent;
    border-left-color: transparent;
    bottom: 0;
    right: 0;
  }
  span {
    font-style: normal;
  }
}
</style>
<style lang="scss">
.video-preview {
  background: none !important;
  box-shadow: none !important;

  .el-dialog__headerbtn .el-dialog__close {
    border-radius: 50%;
    width: 34px;
    height: 34px;
    font-size: 24px;
    color: #fff;
    background-color: var(--el-text-color-regular);
    border-color: #fff;
  }
}

// .el-upload-list {
//   position: absolute !important;
//   z-index: 10;

//   .el-upload-list__item {
//     background: #fff !important;
//     box-shadow: var(--el-box-shadow-light);
//   }
// }
</style>
